package com.mall.order.service.impl;

import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.mall.api.order.dto.OrderDTO;
import com.mall.api.product.ProductFeignClient;
import com.mall.api.product.dto.ProductDTO;
import com.mall.common.exception.BusinessException;
import com.mall.order.entity.Order;
import com.mall.order.entity.OrderItem;
import com.mall.order.mapper.OrderItemMapper;
import com.mall.order.mapper.OrderMapper;
import com.mall.order.service.OrderService;
import io.seata.spring.annotation.GlobalTransactional;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

@Slf4j
@Service
@RequiredArgsConstructor
public class OrderServiceImpl implements OrderService {

    private final OrderMapper orderMapper;
    private final OrderItemMapper orderItemMapper;
    private final ProductFeignClient productFeignClient;

    @Override
    @GlobalTransactional(name = "tx_create_order", rollbackFor = Exception.class)
    @SentinelResource(value = "createOrder", blockHandler = "createOrderBlockHandler", fallback = "createOrderFallback")
    public OrderDTO createOrder(OrderDTO orderDTO) {
        log.info("开始创建订单: {}", orderDTO);
        // 创建订单
        Order order = new Order();
        BeanUtils.copyProperties(orderDTO, order);
        order.setStatus(0);
        order.setCreateTime(LocalDateTime.now());
        order.setUpdateTime(LocalDateTime.now());
        orderMapper.insert(order);
        log.info("订单基本信息创建成功: {}", order.getId());

        // 创建订单项
        List<OrderItem> orderItems = new ArrayList<>();
        for (OrderDTO.OrderItemDTO itemDTO : orderDTO.getItems()) {
            // 检查商品库存
            ProductDTO productDTO = productFeignClient.getProductById(itemDTO.getProductId()).getData();
            if (productDTO == null) {
                log.error("商品不存在: {}", itemDTO.getProductId());
                throw new BusinessException("商品不存在");
            }
            if (productDTO.getStock() < itemDTO.getQuantity()) {
                log.error("商品库存不足: {}, 当前库存: {}, 需要: {}", 
                    productDTO.getName(), productDTO.getStock(), itemDTO.getQuantity());
                throw new BusinessException("商品库存不足");
            }

            // 创建订单项
            OrderItem orderItem = new OrderItem();
            orderItem.setOrderId(order.getId());
            orderItem.setProductId(itemDTO.getProductId());
            orderItem.setQuantity(itemDTO.getQuantity());
            orderItem.setPrice(itemDTO.getPrice());
            orderItem.setCreateTime(LocalDateTime.now());
            orderItem.setUpdateTime(LocalDateTime.now());
            orderItemMapper.insert(orderItem);
            orderItems.add(orderItem);
            log.info("订单项创建成功: {}", orderItem.getId());

            // 更新商品库存
            log.info("更新商品库存: 商品ID: {}, 原库存: {}, 减少数量: {}", 
                itemDTO.getProductId(), productDTO.getStock(), itemDTO.getQuantity());
            productFeignClient.updateStock(itemDTO.getProductId(), productDTO.getStock() - itemDTO.getQuantity());
        }

        log.info("订单创建成功: {}", order.getId());
        return convertToDTO(order, orderItems);
    }

    // Sentinel 流控处理方法
    public OrderDTO createOrderBlockHandler(OrderDTO orderDTO, BlockException e) {
        log.error("订单创建被限流，userId: {}", orderDTO.getUserId());
        throw new BusinessException(429, "当前下单人数过多，请稍后再试");
    }

    // Sentinel 熔断处理方法
    public OrderDTO createOrderFallback(OrderDTO orderDTO, Throwable e) {
        log.error("订单创建失败，服务降级，userId: {}, error: {}", orderDTO.getUserId(), e.getMessage());
        throw new BusinessException("创建订单失败，请稍后再试");
    }

    @Override
    @SentinelResource(value = "getOrderById", blockHandler = "getOrderByIdBlockHandler", fallback = "getOrderByIdFallback")
    public OrderDTO getOrderById(Long id) {
        Order order = orderMapper.selectById(id);
        if (order == null) {
            throw new BusinessException("订单不存在");
        }

        List<OrderItem> orderItems = orderItemMapper.selectList(
                new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<OrderItem>()
                        .eq(OrderItem::getOrderId, id));

        return convertToDTO(order, orderItems);
    }

    // Sentinel 流控处理方法
    public OrderDTO getOrderByIdBlockHandler(Long id, BlockException e) {
        log.error("订单查询被限流，id: {}", id);
        throw new BusinessException(429, "当前查询人数过多，请稍后再试");
    }

    // Sentinel 熔断处理方法
    public OrderDTO getOrderByIdFallback(Long id, Throwable e) {
        log.error("订单查询失败，服务降级，id: {}, error: {}", id, e.getMessage());
        throw new BusinessException("查询订单失败，请稍后再试");
    }

    @Override
    @SentinelResource(value = "getOrderByUserId", blockHandler = "getOrderByUserIdBlockHandler", fallback = "getOrderByUserIdFallback")
    public OrderDTO getOrderByUserId(Long userId) {
        Order order = orderMapper.selectOne(
                new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<Order>()
                        .eq(Order::getUserId, userId));
        if (order == null) {
            throw new BusinessException("订单不存在");
        }

        List<OrderItem> orderItems = orderItemMapper.selectList(
                new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<OrderItem>()
                        .eq(OrderItem::getOrderId, order.getId()));

        return convertToDTO(order, orderItems);
    }

    // Sentinel 流控处理方法
    public OrderDTO getOrderByUserIdBlockHandler(Long userId, BlockException e) {
        log.error("订单查询被限流，userId: {}", userId);
        throw new BusinessException(429, "当前查询人数过多，请稍后再试");
    }

    // Sentinel 熔断处理方法
    public OrderDTO getOrderByUserIdFallback(Long userId, Throwable e) {
        log.error("订单查询失败，服务降级，userId: {}, error: {}", userId, e.getMessage());
        throw new BusinessException("查询订单失败，请稍后再试");
    }

    @Override
    @GlobalTransactional(name = "tx_update_order_status", rollbackFor = Exception.class)
    @SentinelResource(value = "updateOrderStatus", blockHandler = "updateOrderStatusBlockHandler", fallback = "updateOrderStatusFallback")
    public void updateOrderStatus(Long id, Integer status) {
        log.info("开始更新订单状态: 订单ID: {}, 新状态: {}", id, status);
        Order order = orderMapper.selectById(id);
        if (order == null) {
            log.error("订单不存在: {}", id);
            throw new BusinessException("订单不存在");
        }

        order.setStatus(status);
        order.setUpdateTime(LocalDateTime.now());
        orderMapper.updateById(order);
        log.info("订单状态更新成功: {}", id);
    }

    // Sentinel 流控处理方法
    public void updateOrderStatusBlockHandler(Long id, Integer status, BlockException e) {
        log.error("订单状态更新被限流，id: {}, status: {}", id, status);
        throw new BusinessException(429, "当前更新人数过多，请稍后再试");
    }

    // Sentinel 熔断处理方法
    public void updateOrderStatusFallback(Long id, Integer status, Throwable e) {
        log.error("订单状态更新失败，服务降级，id: {}, status: {}, error: {}", id, status, e.getMessage());
        throw new BusinessException("更新订单状态失败，请稍后再试");
    }

    @Override
    @GlobalTransactional(name = "tx_delete_order", rollbackFor = Exception.class)
    @SentinelResource(value = "deleteOrder", blockHandler = "deleteOrderBlockHandler", fallback = "deleteOrderFallback")
    public void deleteOrder(Long id) {
        log.info("开始删除订单: {}", id);
        if (orderMapper.deleteById(id) == 0) {
            log.error("订单不存在: {}", id);
            throw new BusinessException("订单不存在");
        }
        
        log.info("删除订单项: 订单ID: {}", id);
        orderItemMapper.delete(
                new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<OrderItem>()
                        .eq(OrderItem::getOrderId, id));
        
        log.info("订单删除成功: {}", id);
    }

    // Sentinel 流控处理方法
    public void deleteOrderBlockHandler(Long id, BlockException e) {
        log.error("订单删除被限流，id: {}", id);
        throw new BusinessException(429, "当前删除人数过多，请稍后再试");
    }

    // Sentinel 熔断处理方法
    public void deleteOrderFallback(Long id, Throwable e) {
        log.error("订单删除失败，服务降级，id: {}, error: {}", id, e.getMessage());
        throw new BusinessException("删除订单失败，请稍后再试");
    }

    private OrderDTO convertToDTO(Order order, List<OrderItem> orderItems) {
        OrderDTO orderDTO = new OrderDTO();
        BeanUtils.copyProperties(order, orderDTO);

        List<OrderDTO.OrderItemDTO> itemDTOs = new ArrayList<>();
        for (OrderItem orderItem : orderItems) {
            OrderDTO.OrderItemDTO itemDTO = new OrderDTO.OrderItemDTO();
            BeanUtils.copyProperties(orderItem, itemDTO);
            itemDTOs.add(itemDTO);
        }
        orderDTO.setItems(itemDTOs);

        return orderDTO;
    }
} 